﻿/*
 * 5-10-2010 - Alowan Hermes - 0922412
 * 
 * */

using System.Collections.Generic;
using System.Linq;
using System.Drawing;
using Roborally.CommonData.GlobaleTypes;
using Roborally.Scheidsrechter;
using System.Threading;
using System;

namespace Roborally.Spelleider
{
    /// <summary>
    /// Een instantie van deze klasse regelt het hele spel verloop.
    /// </summary>
    public class Spelleider
    {
        #region Fields en Properties
        Deck<IProgramKaart> deck;
        int MaxVlagnummer;
        List<SpelerInfo> spelersInfo;
        IModel speelbord;
        ScheidsRechter scheidsRechter;
        KaartOperaties kaartOperaties;
        ZandLoper scheduler;
        Thread doe_doorspelen;

        public int rondeNummer;
        internal List<SpelerInfo> SpelersInfo { get { return spelersInfo; } }

        /// <summary>
        /// Wordt geraised wanneer kaarten uitgedeeld worden.
        /// </summary>
        public event DeelKaartenEventHandler DeelKaartenEvent;


        public event SpelGewonnenEventHandeler SpelGewonnen;

        /// <summary>
        /// Wordt geraised wanneer alle spelers verplaatst worden.
        /// </summary>
        public event VerplaatsAlleSpelersEventHandler VerplaatsAlleSpelers;
        #endregion

        internal Spelleider()
        {
            spelersInfo = new List<SpelerInfo>();
            scheidsRechter = new ScheidsRechter();
            kaartOperaties = new KaartOperaties();
            scheduler = new ZandLoper(this, scheidsRechter);

            rondeNummer = 1;
        }

        public Spelleider(SpelInformatie spelinfo)
            : this()
        {
            //Opslaan van speelbord
            speelbord = spelinfo.Model;

            //Maak alle checkpoints aan op het bord
            MaxVlagnummer = 0;
            for (int k = 0; k < speelbord.Vakken.GetLength(0); k++)
            {
                for (int j = 0; j < speelbord.Vakken.GetLength(1); j++)
                {
                    IVak vakje = speelbord.Vakken[k, j];
                    if (vakje != null && vakje.KrijgType() == CommonData.Enums.VakType.Checkpoint && vakje.CheckpointNummer() > MaxVlagnummer)
                    {
                        MaxVlagnummer = speelbord.Vakken[k, j].CheckpointNummer();
                    }
                }
            }

            //Bepaal waar docking bay is.
            List<Point> startpunten = StartPunten();

            //Maak spelers en AI aan
            int startPunt = 0;
            foreach (KeyValuePair<int, string> speler in spelinfo.SpelerIdEnNaam)
            {
                //Speler is AI?
                bool isAI = false;

                //werkt niet
                //for (int i = 0; i < spelinfo.AantalRobots.Length && !isAI; i++)
                //    isAI = (spelinfo.AantalRobots[i] == speler.Key);

                SpelerInfo info = null;
                if (isAI)
                {
                    //Maak AI aan en koppel events nodig voor algoritme
                    info = new SpelerInfo(speler.Key, startpunten[startPunt], new Algoritme_Groep10.Algoritme());
                    info.AI.LegKaartNeer += SpelerLegtKaartenNeer;
                    info.AI.VoerZetUit += VoerZetUitAI;
                }
                else //Maakt een speler aan
                    info = new SpelerInfo(speler.Key, startpunten[startPunt]);

                //Voegt speler toe aan spelers lijst
                spelersInfo.Add(info);
                startPunt++;
            }
        }

        private List<Point> StartPunten()
        {
            List<Point> startPunten = new List<Point>();
            //Bord is 2 hoog (oftwel 12 + 12 + docking bay van 4)
            bool TweeLang = (speelbord.Vakken.GetLength(1) >= 17);

            if (!TweeLang)
            {
                if (speelbord.Vakken[0, 13] != null)//Als het veld een lang is dan zit de dockingbay aan de linker kant.
                {
                    Point punt = new Point(5, 15);
                    startPunten.Add(punt);
                    punt = new Point(6, 15);
                    startPunten.Add(punt);
                    punt = new Point(3, 4);
                    startPunten.Add(punt);
                    punt = new Point(8, 14);
                    startPunten.Add(punt);
                    punt = new Point(1, 13);
                    startPunten.Add(punt);
                    punt = new Point(10, 3);
                    startPunten.Add(punt);
                    punt = new Point(0, 12);
                    startPunten.Add(punt);
                    punt = new Point(11, 12);
                    startPunten.Add(punt);
                }
                else if (speelbord.Vakken.GetLength(0) >= 13 && speelbord.Vakken[13, 13] != null) //Zit de dockingbay aan de rechter kant.
                {
                    Point punt = new Point(17, 15);
                    startPunten.Add(punt);
                    punt = new Point(18, 15);
                    startPunten.Add(punt);
                    punt = new Point(15, 14);
                    startPunten.Add(punt);
                    punt = new Point(20, 14);
                    startPunten.Add(punt);
                    punt = new Point(13, 13);
                    startPunten.Add(punt);
                    punt = new Point(22, 13);
                    startPunten.Add(punt);
                    punt = new Point(12, 12);
                    startPunten.Add(punt);
                    punt = new Point(23, 12);
                    startPunten.Add(punt);
                }
            }
            else
            {
                if (speelbord.Vakken[0, 25] != null)//Als het veld twee lang is dan zit de dockingbay aan de linker kant.
                {
                    Point punt = new Point(17, 27);
                    startPunten.Add(punt);
                    punt = new Point(18, 27);
                    startPunten.Add(punt);
                    punt = new Point(15, 26);
                    startPunten.Add(punt);
                    punt = new Point(20, 26);
                    startPunten.Add(punt);
                    punt = new Point(13, 25);
                    startPunten.Add(punt);
                    punt = new Point(22, 25);
                    startPunten.Add(punt);
                    punt = new Point(12, 24);
                    startPunten.Add(punt);
                    punt = new Point(23, 24);
                    startPunten.Add(punt);
                }
                else if (speelbord.Vakken.GetLength(0) >= 13 && speelbord.Vakken[13, 25] != null) //Zit de dockingbay aan de rechter kant.
                {
                    Point punt = new Point(5, 27);
                    startPunten.Add(punt);
                    punt = new Point(6, 27);
                    startPunten.Add(punt);
                    punt = new Point(3, 26);
                    startPunten.Add(punt);
                    punt = new Point(8, 26);
                    startPunten.Add(punt);
                    punt = new Point(1, 25);
                    startPunten.Add(punt);
                    punt = new Point(10, 25);
                    startPunten.Add(punt);
                    punt = new Point(0, 24);
                    startPunten.Add(punt);
                    punt = new Point(11, 24);
                    startPunten.Add(punt);
                }
            }
            return startPunten;
        }
        private SpelerGegevens VoerZetUitAI(SpelerGegevens Speler, IProgramKaart Kaart)
        {
            //Aanmaken input
            SpelerGegevens copy = Speler.Copy();
            InputScheidsrechter input = new InputScheidsrechter()
            {
                GegevensEenSpeler = copy,
                Kaart = Kaart,
                Model = speelbord
            };
            foreach (SpelerInfo tmp in spelersInfo)
            {
                if (tmp.Id == copy.Speler)
                {
                    input.GegevensSpelers = getSpelerGegevensZonder(tmp);
                    break;
                }
            }

            //Fase 1 voer zet uit voor spelers beurt
            ReturnScheidsrechter output = scheidsRechter.VoerZetUit(input);
            //Fase 2 Voer loopbanden uit
            input.GegevensEenSpeler = output.GegevensEenSpeler;
            output = scheidsRechter.Loopbanden(input);
            //Fase 2 Voer  draaien uit
            input.GegevensEenSpeler = output.GegevensEenSpeler;
            output = scheidsRechter.Draaien(input);
            //Fase 2 Voer pushers uit
            input.GegevensEenSpeler = output.GegevensEenSpeler;
            output = scheidsRechter.Pushers(input);
            //Fase 3 Voer lasers uit
            input.GegevensEenSpeler = output.GegevensEenSpeler;
            output = scheidsRechter.Loopbanden(input);

            return output.GegevensEenSpeler;
        }



        /// <summary>
        /// Dient aangeroepen te worden wanneer een speler zijn kaarten neerlegt
        /// </summary>
        /// <param name="data">De informatie betreffende de kaarten van een speler</param>
        /// <returns>Of de speler deze vijf kaarten wel gekregen heeft</returns>
        public bool SpelerLegtKaartenNeer(SpelerLegtKaartenArgs data)
        {
            bool result = controleerKaart(data);
            if (result)
            {
                foreach (SpelerInfo speler in spelersInfo)
                {
                    if (data != null && data.SpelerIdentificatie == speler.Id)
                        speler.LegtKaartenNeer(data.GekozenKaart, data.KaartVakNummer);
                }
            }
            return result;
        }

        /// <summary>
        /// Draait de eerstvolgende kaart om van iedere speler
        /// </summary>
        /// <returns>Een Dictionary met SpelerInfo en ProgramKaart bevattend; iedere speler met omgedraaide kaart</returns>
        private Dictionary<SpelerInfo, IProgramKaart> draaiKaartenOm(int beurtNummer)
        {
            Dictionary<SpelerInfo, IProgramKaart> dict = new Dictionary<SpelerInfo, IProgramKaart>();
            for (int i = 0; i < spelersInfo.Count; i++)
            {
                SpelerInfo speler = spelersInfo[i];
                if (speler.Dood || speler.PowerDown || speler.Locatie == new Point(-1, -1))
                    continue;
                IProgramKaart kaart = speler.PeekKaartVanProgramBay(beurtNummer);
                dict.Add(speler, kaart);
            }
            return dict;
        }

        /// <summary>
        /// Sorteert een gegeven Dictionary met SpelerInfo en ProgramKaart zo 
        /// dat de eerste SpelerInfo de kaart met hoogste prioriteit heeft
        /// </summary>
        /// <param name="ongesorteerd">De Dictionary die gesorteerd moet worden</param>
        /// <returns>Een Dictionary met SpelerInfo en ProgramKaart gesorteerd op Kaart prioriteit</returns>
        private Dictionary<SpelerInfo, IProgramKaart> sorteerOpPrioriteit(Dictionary<SpelerInfo, IProgramKaart> ongesorteerd)
        {
            Dictionary<SpelerInfo, IProgramKaart> dict = new Dictionary<SpelerInfo, IProgramKaart>();
            List<int> prioriteiten = getPrioriteiten(ongesorteerd.Values.ToList<IProgramKaart>());
            InputScheidsrechter input = new InputScheidsrechter();
            input.Prioriteiten = prioriteiten;
            ReturnScheidsrechter output = scheidsRechter.VraagVolgorde(input);
            prioriteiten = output.Prioriteiten;
            while (prioriteiten.Count > 0)
            {
                int index = getKaartIndex(ongesorteerd.Values.ToList<IProgramKaart>(), prioriteiten[0]);
                prioriteiten.RemoveAt(0);
                dict.Add(ongesorteerd.Keys.ToList<SpelerInfo>()[index], ongesorteerd.Values.ToList<IProgramKaart>()[index]);
            }
            return dict;
        }

        /// <summary>
        /// Geeft een lijst met prioriteiten van gegeven kaarten
        /// </summary>
        /// <param name="kaarten">De lijst met ProgramKaart waarvan de prioriteit gegeven moet worden</param>
        /// <returns>Een Lijst van ints met de prioriteit van iedere kaart (in dezelfde volgorde als de gegeven lijst)</returns>
        private List<int> getPrioriteiten(List<IProgramKaart> kaarten)
        {
            List<int> prioriteiten = new List<int>();
            foreach (IProgramKaart kaart in kaarten)
                prioriteiten.Add(kaart.Prioriteit);
            return prioriteiten;
        }

        /// <summary>
        /// Loopt door alle spelers met kaarten om de zetten uit te voeren
        /// </summary>
        /// <param name="bord">Het IBord</param>
        /// <param name="spelersEnKaarten">De spelers met kaarten</param>
        private void voerZettenUit(IModel bord, Dictionary<SpelerInfo, IProgramKaart> spelersEnKaarten)
        {
            foreach (KeyValuePair<SpelerInfo, IProgramKaart> kvp in spelersEnKaarten)
            {
                voerZetUit(bord, kvp.Key, kvp.Value);
            }
        }


        /// <summary>
        /// Voert een zet uit van een speler
        /// </summary>
        /// <param name="bord">Het bord waar de zet op wordt gedaan</param>
        /// <param name="speler">De speler die de zet doet</param>
        /// <param name="kaart">De kaart</param>
        private void voerZetUit(IModel bord, SpelerInfo speler, IProgramKaart kaart)
        {
            if (speler.Dood || speler.Locatie == new Point(-1, -1))
                return;
            InputScheidsrechter input = new InputScheidsrechter();
            input.Kaart = kaart;
            input.Model = bord;
            input.GegevensEenSpeler = speler.ToSpelerGegevens();
            input.GegevensSpelers = getSpelerGegevensZonder(speler);
            ReturnScheidsrechter output = scheidsRechter.VoerZetUit(input);
            verwerkOutput(output);
        }

        /// <summary>
        /// Geeft een lijst met spelergegevens van alle spelers behalve een gegeven speler
        /// </summary>
        /// <param name="speler"></param>
        /// <returns></returns>
        private List<SpelerGegevens> getSpelerGegevensZonder(SpelerInfo speler)
        {
            List<SpelerGegevens> output = new List<SpelerGegevens>();
            foreach (SpelerInfo s in spelersInfo)
                if (s.Equals(speler) || s.Dood || s.Locatie == new Point(-1, -1))
                    continue;
                else
                    output.Add(s.ToSpelerGegevens());
            return output;
        }

        /// <summary>
        /// Geeft een lijst met spelergegevens van alle spelers
        /// </summary>
        /// <returns>Een lijst met SpelerGegevens</returns>
        private List<SpelerGegevens> getSpelerGegevens()
        {
            List<SpelerGegevens> output = new List<SpelerGegevens>();
            foreach (SpelerInfo s in spelersInfo)
                if (s.Dood || s.Locatie == new Point(-1, -1))
                    continue;
                else
                    output.Add(s.ToSpelerGegevens());
            return output;
        }


        #region Fase2
        private void voerLoopbandenUit(IModel bord, List<SpelerGegevens> spelerGegevens)
        {
            InputScheidsrechter input = new InputScheidsrechter();
            input.Model = bord;
            input.GegevensSpelers = spelerGegevens;
            ReturnScheidsrechter output = scheidsRechter.Loopbanden(input);
            verwerkOutput(output);
        }


        private void voerDraaienUit(IModel bord, List<SpelerGegevens> spelerGegevens)
        {
            InputScheidsrechter input = new InputScheidsrechter();
            input.Model = bord;
            input.GegevensSpelers = spelerGegevens;
            ReturnScheidsrechter output = scheidsRechter.Draaien(input);
            verwerkOutput(output);
        }

        private void voerPushersUit(IModel bord, int beurtNummer, List<SpelerGegevens> spelerGegevens)
        {
            InputScheidsrechter input = new InputScheidsrechter();
            input.Model = bord;
            input.RegistratieFase = beurtNummer;
            input.GegevensSpelers = spelerGegevens;
            ReturnScheidsrechter output = scheidsRechter.Pushers(input);
            verwerkOutput(output);
        }
        #endregion

        #region Fase3
        private void voerLasersUit(IModel bord, List<SpelerGegevens> spelerGegevens)
        {
            InputScheidsrechter input = new InputScheidsrechter();
            input.Model = bord;
            input.GegevensSpelers = spelerGegevens;
            ReturnScheidsrechter output = scheidsRechter.Lasers(input);
            verwerkOutput(output);
        }
        #endregion

        #region EindBeurt
        /// <summary>
        /// 
        /// </summary>
        /// <param name="bord"></param>
        /// <param name="spelerGegevens"></param>
        private void voerEindUit(IModel bord, List<SpelerGegevens> spelerGegevens)
        {
            InputScheidsrechter input = new InputScheidsrechter();
            input.Model = bord;
            input.GegevensSpelers = spelerGegevens;
            ReturnScheidsrechter output = scheidsRechter.Eind(input);
            verwerkOutput(output);



        }

        /// <summary>
        /// Vraagt de eindposities op en verwerkt deze meteen
        /// </summary>
        /// <param name="bord"></param>
        /// <param name="spelerGegevens"></param>
        private void voerVraagBeginPositieUit(IModel bord, List<SpelerGegevens> spelerGegevens)
        {
            //    InputScheidsrechter input = new InputScheidsrechter();
            //    input.Bord = bord;
            //    input.GegevensSpelers = spelerGegevens;
            //    ReturnScheidsrechter output = scheidsRechter.(input);
            //    verwerkOutput(output);
        }
        #endregion

        #region VerwerkOutput
        /// <summary>
        /// Verwerkt de output van een scheidsrechter return
        /// </summary>
        /// <param name="output">De ReturnScheidRechter met de output</param>
        private void verwerkOutput(ReturnScheidsrechter output)
        {
            if (output == null)
                return;
            List<SpelerZetGegevens> zetten = new List<SpelerZetGegevens>();
            foreach (SpelerInfo speler in spelersInfo)
            {
                //Twan Wolthof - 0910740
                //De Interfacetype ISpeler bevat niks en kan ook niet vergeleken worden met een int.
                if (output.GegevensEenSpeler != null && output.GegevensEenSpeler.Speler == speler.Id)
                {
                    verwerkOutputVan(speler, output.GegevensEenSpeler);
                    //letop gecommeenteerd 
                    //continue;
                }
                foreach (SpelerGegevens gegevens in output.GegevensSpelers)
                {
                    //Twan Wolthof - 0910740
                    //De Interfacetype ISpeler bevat niks en kan ook niet vergeleken worden met een int.
                    if (gegevens.Speler == speler.Id)
                    {
                        verwerkOutputVan(speler, gegevens);
                        break;
                    }
                }

                SpelerZetGegevens z = new SpelerZetGegevens(speler.Id, speler.ProgrammeerBaai, beurtNummer, speler.Locatie,
                    speler.OudeLocatie, speler.Richting, speler.Schade, speler.Levens, speler.PowerDown);
                zetten.Add(z);
            }

            //event firen
            if (VerplaatsAlleSpelers != null)
                VerplaatsAlleSpelers(new SpelerLocaties(zetten));
        }

        /// <summary>
        /// Verwerkt de gegevens van een speler
        /// </summary>
        /// <param name="speler">De speler</param>
        /// <param name="gegevens">De nieuwe gegevens</param>
        private void verwerkOutputVan(SpelerInfo speler, SpelerGegevens gegevens)
        {
            speler.Schade += gegevens.Damage;
            if (!speler.Dood && speler.Locatie != new Point(-1, -1))
            {
                speler.Locatie = gegevens.Positie;
                speler.Richting = gegevens.Richting;
                if (gegevens.BeginPositie)
                    speler.RespawnLocatie = gegevens.Positie;
                if (gegevens.VlagBehaald)
                {
                    speler.AantalBehaaldeVlaggen++;
                    if (speler.AantalBehaaldeVlaggen == MaxVlagnummer)
                    {
                        SpelGewonnen(speler.Id);
                    }
                }
            }
        }
        #endregion


        public int beurtNummer;
        /// <summary>
        /// Speelt een hele beurt (meerdere fases)
        /// </summary>
        /// <param name="bord"></param>
        private void speelBeurt(IModel bord, int beurtNummer)
        {
            //Fase 1 Draai kaarten om
            Dictionary<SpelerInfo, IProgramKaart> spelersEnKaarten = draaiKaartenOm(beurtNummer - 1);
            //Fase 1 Sorteer de kaarten op prioriteit
            spelersEnKaarten = sorteerOpPrioriteit(spelersEnKaarten);
            //Fase 1 Voer zetten uit
            voerZettenUit(bord, spelersEnKaarten);
            //Fase 2 Voer loopbanden uit
            voerLoopbandenUit(bord, getSpelerGegevens());
            //Fase 2 Voer  draaien uit
            voerDraaienUit(bord, getSpelerGegevens());
            //Fase 2 Voer pushers uit
            voerPushersUit(bord, beurtNummer, getSpelerGegevens());
            //Fase 3 Voer lasers uit
            voerLasersUit(bord, getSpelerGegevens());
            if (beurtNummer == 5)
            {
                voerEindUit(bord, getSpelerGegevens());
                respawnDodeSpelers();
                voerVraagBeginPositieUit(bord, getSpelerGegevens());
            }
        }

        /// <summary>
        /// Zorgt ervoor dat dode spelers gerespawned worden
        /// </summary>
        private void respawnDodeSpelers()
        {
            foreach (SpelerInfo speler in spelersInfo)
            {
                if (speler.Locatie == new Point(-1, -1))
                {
                    speler.Locatie = speler.RespawnLocatie;
                }
            }
        }

        /// <summary>
        /// Zoekt de index van een kaart uit de programkaarten van een speler,
        /// gelijk is aan een bepaalde prioriteit.
        /// </summary>
        /// <param name="kaarten"></param>
        /// <param name="prioriteit"></param>
        /// <returns></returns>
        private int getKaartIndex(List<IProgramKaart> kaarten, int prioriteit)
        {
            for (int i = 0; i < kaarten.Count; i++)
            {
                if (prioriteit == kaarten[i].Prioriteit)
                    return i;
            }
            return -1;
        }


        /// <summary>
        /// Controleert of de speler een kaart neerlegt die hij daadwerkelijk heeft gekregen
        /// En controleert of de timer gestart moet worden
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        private bool controleerKaart(SpelerLegtKaartenArgs data)
        {
            bool result = false;
            SpelerInfo speler = null;
            for (int i = 0; i < spelersInfo.Count && speler == null; i++)
            {
                if (spelersInfo[i].Id == data.SpelerIdentificatie)
                    speler = spelersInfo[i];

            }
            if (speler != null)
            {
                result = kaartOperaties.ControleerKaart(data.GekozenKaart, speler);
                if (result)
                {
                    bool kaartenGelegd = true;
                    for (int i = 0; i < speler.ProgrammeerBaai.Count && kaartenGelegd; i++)
                        kaartenGelegd = (speler.ProgrammeerBaai[i] == null || i == data.KaartVakNummer);
                    if (kaartenGelegd)
                        scheduler.ControleerTimer(data);
                }
            }
            //bool AlleKaartenLegaal=true;
            //foreach (ProgramKaart kaart in spelersInfo[data.SpelerIdentificatie].ProgrammeerBaai)
            //{
            //    if(kaart == null)
            //    {
            //    AlleKaartenLegaal = false;
            //    }

            //}
            //if (AlleKaartenLegaal)
            //{

            //}
            return result;
        }

        private delegate void GeefKaartenAI(List<IProgramKaart> Kaarten, SpelerGegevens Speler, IModel Bord);
        /// <summary>
        /// Deelt het aantal kaarten (dat de speler mag ontvangen) uit aan de spelers
        /// en firet het event dat aangeeft welke kaarten zijn uitgedeeld
        /// </summary>
        private void uitdelenKaarten()
        {
            Dictionary<int, List<IProgramKaart>> spelerIDsEnKaartenDict = new Dictionary<int, List<IProgramKaart>>();
            deck = Deck<IProgramKaart>.ProgramDeck();
            deck.Schudden();

            foreach (SpelerInfo spelerInfo in spelersInfo)
            {
                if (!(spelerInfo.PowerDown || spelerInfo.Dood))
                {
                    //Vraag aantal kaarten a.d.h.v. schadepunten
                    InputScheidsrechter input = new InputScheidsrechter();
                    input.Schadepunten = spelerInfo.Schade;
                    List<IProgramKaart> kaarten = deck.Pakken(scheidsRechter.VraagAantalKaarten(input).AantalKaarten);

                    //Geef kaarten aan AI en normale spelers
                    spelerInfo.KrijgtKaarten(kaarten);
                    //Voeg informatie toe aan spelerIDsEnKaarten
                    spelerIDsEnKaartenDict.Add(spelerInfo.Id, spelerInfo.Hand);

                    // AI voert algoritme uit
                    if (spelerInfo.IsAI)
                    {
                        GeefKaartenAI krijgtKaarten = spelerInfo.AI.KrijgtKaarten;
                        krijgtKaarten.BeginInvoke(kaarten, spelerInfo.ToSpelerGegevens(), speelbord, null, null);
                    }
                }
            }

            //Waarschuwt MVC dat de kaarten uitgedeeld zijn
            if (DeelKaartenEvent != null)
                DeelKaartenEvent(new SpelerIDsEnKaarten(spelerIDsEnKaartenDict));
        }


        /// <summary>
        /// Start het spel, aangeroepen door MVC
        /// </summary>
        public void StartSpel()
        {
            /*while (true)
            {
                //System.Console.WriteLine("ty for while(true) Spelleider");
                if (!kaartenUitgedeeld)
                {
                    kaartenUitgedeeld = true;
                    uitdelenKaarten();
                }
                if (AlleSpelersKaartenGelegd)
                {
                    StartRonde();
                    kaartenUitgedeeld = false;
                }
            }*/
            doe_doorspelen = new Thread(do_iet);
            doe_doorspelen.Start();
        }

        private void do_iet()
        {
            //warning this is dirty...
            //just remove the thread crap and call this thing everytime a card is handled or smthing
            while (true)
            {
                if (!kaartenUitgedeeld)
                {
                    kaartenUitgedeeld = true;
                    uitdelenKaarten();
                }
                if (AlleSpelersKaartenGelegd)
                {
                    Console.WriteLine("Iedereen heeft gelegd.");
                    StartRonde();
                    kaartenUitgedeeld = false;
                }
                Thread.Sleep(1000);
            }
        }



        /// <summary>
        /// Start een ronde
        /// </summary>
        /// <param name="rondeNummer">Ronde nummer</param>
        internal void StartRonde()
        {
            beurtNummer = 1;
            while (beurtNummer < 6)
                startBeurt();
            rondeNummer++;
            uitdelenKaarten();

            //Alle kaarten innemen van spelers aan einde ronde
        }

        /// <summary>
        /// Start een beurt nadat alle kaarten gelegd zijn
        /// Wordt aangeroepen vanuit Scheduler
        /// </summary>
        private void startBeurt()
        {
            //alle kaarten zijn gelegd, nieuwe ronde

            speelBeurt(speelbord, beurtNummer);
            beurtNummer++;
        }


        internal void legKaartenNeerVoor(int laatsteSpelerId)
        {
            foreach (SpelerInfo speler in spelersInfo)
            {
                if (speler.Id == laatsteSpelerId)
                {
                    speler.LegRandomKaartenNeer();
                    return;
                }
            }
        }

        bool alleSpelersKaartenGelegd;
        bool kaartenUitgedeeld;
        public bool AlleSpelersKaartenGelegd
        {
            get
            {
                bool result = true;
                for (int i = 0; i < spelersInfo.Count && result; i++)
                {
                    result = spelersInfo[i].AlleKaartenInProgrammeerBaai;
                }
                if (result)
                {
                    Console.WriteLine("Alle spelers zijn klaar!");
                }
                return result;
            }
        }

    }
}